package com.hyjiacan.apps.audionly.util

import com.hyjiacan.apps.audionly.utils.ExoAudioExtractor
import android.content.Context
import androidx.test.core.app.ApplicationProvider

import com.hyjiacan.apps.audionly.data.model.AudioParam
import com.hyjiacan.apps.audionly.data.model.FileProgress
import com.hyjiacan.apps.audionly.data.model.TaskInfo
import com.hyjiacan.apps.audionly.data.model.VideoFile
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Assertions.*
import io.mockk.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.*
import org.junit.jupiter.api.extension.ExtendWith
import io.mockk.junit5.MockKExtension
import java.io.File
import java.util.Date
import java.util.UUID

/**
 * ExoAudioExtractor类的单元测试
 */
@ExperimentalCoroutinesApi
@ExtendWith(MockKExtension::class)
class ExoAudioExtractorTest {
    private val testDispatcher = StandardTestDispatcher()
    private val context = ApplicationProvider.getApplicationContext<Context>()
private val extractor = ExoAudioExtractor(context)

    @Test
    fun `test extractAudio with valid parameters`() = runTest(testDispatcher) {
        // 创建测试任务
        val videoFile = File.createTempFile("test", ".mp4")
        val videoFileInfo = VideoFile(
            id = UUID.randomUUID().toString(),
            name = videoFile.name,
            path = videoFile.absolutePath,
            duration = 10000,
            size = videoFile.length(),
            format = "mp4"
        )

        val audioParam = AudioParam(format = "mp3")
        val taskInfo = TaskInfo(
            id = UUID.randomUUID().toString(),
            videoFile = videoFileInfo,
            audioParam = audioParam,
            status = TaskInfo.Status.PROCESSING,
            createTime = Date()
        )

        // 模拟进度更新回调
        val progressCallback = mockk<(FileProgress) -> Unit>()
        // 设置默认行为
        every { progressCallback.invoke(any()) } returns Unit

        // 运行测试
        val result = extractor.extractAudio(taskInfo, progressCallback)

        // 验证结果
        assertTrue(result)
        assertNotNull(taskInfo.outputPath)
        assertTrue(File(taskInfo.outputPath!!).parentFile!!.exists())

        // 验证进度回调被调用
        verify(atLeast = 1) { progressCallback.invoke(any()) }

        // 清理临时文件
        videoFile.delete()
        taskInfo.outputPath?.let { File(it).parentFile?.deleteRecursively() }
    }

    @Test
    fun `test extractAudio with non-existent video file`() = runTest(testDispatcher) {
        // 创建测试任务，使用不存在的视频文件
        val videoFileInfo = VideoFile(
            id = UUID.randomUUID().toString(),
            name = "non_existent.mp4",
            path = "/non/existent/path/non_existent.mp4",
            duration = 10000,
            size = 5242880,
            format = "mp4"
        )

        val audioParam = AudioParam()
        val taskInfo = TaskInfo(
            id = UUID.randomUUID().toString(),
            videoFile = videoFileInfo,
            audioParam = audioParam,
            status = TaskInfo.Status.PROCESSING,
            createTime = Date()
        )

        // 模拟进度更新回调
        val progressCallback = mockk<(FileProgress) -> Unit>()
        // 设置默认行为
        every { progressCallback.invoke(any()) } returns Unit

        // 运行测试
        val result = extractor.extractAudio(taskInfo, progressCallback)

        // 验证结果
        assertFalse(result)
        assertNull(taskInfo.outputPath)

        // 验证进度回调未被调用
        verify(exactly = 0) { progressCallback.invoke(any()) }
        verify(exactly = 0) { progressCallback.invoke(any()) }
    }

    @Test
    fun `test extractAudio with output directory creation failure`() = runTest(testDispatcher) {
        // 创建测试任务
        val videoFile = File.createTempFile("test", ".mp4")
        val videoFileInfo = VideoFile(
            id = UUID.randomUUID().toString(),
            name = videoFile.name,
            path = videoFile.absolutePath,
            duration = 10000,
            size = videoFile.length(),
            format = "mp4"
        )

        val audioParam = AudioParam()
        val taskInfo = TaskInfo(
            id = UUID.randomUUID().toString(),
            videoFile = videoFileInfo,
            audioParam = audioParam,
            status = TaskInfo.Status.PROCESSING,
            createTime = Date()
        )

        // 模拟进度更新回调
        val progressCallback = mockk<(FileProgress) -> Unit>()
        // 设置默认行为
        every { progressCallback.invoke(any()) } returns Unit

        // 尝试创建一个不可写的目录
        val outputDir = File(videoFile.absolutePath + ".extract")
        outputDir.mkdirs()
        outputDir.setWritable(false)

        try {
            // 运行测试
            val result = extractor.extractAudio(taskInfo, progressCallback)

            // 验证结果
            assertFalse(result)
            assertNull(taskInfo.outputPath)

            // 验证进度回调未被调用
            verify(exactly = 0) { progressCallback.invoke(any()) }
        } finally {
            // 恢复目录权限以便清理
            outputDir.setWritable(true)
            videoFile.delete()
            outputDir.deleteRecursively()
        }
    }
}